#include "type.h"
#include "dbg.h"
#include "stdio.h"
#include "string.h"

#include "fs/fs.h"
#include "fs/deffs.h"
#include "fs/ide.h"
#include "fs/ramdisk.h"

extern byte_t _binary_bin_fat32_img_start[], _binary_bin_fat32_img_end[];

bool
check_initrd(const byte_t _initrd_begin[], const byte_t _initrd_end[]) {
    if (_initrd_begin == _initrd_end) {
        printf("warning: no initrd!\n");
        return FALSE;
    }
    printf("Initrd: 0x%08x - 0x%08x,size: 0x%08x\n", _initrd_begin, _initrd_end - 1, _initrd_end - _initrd_begin);
    return TRUE;
}

static int
ramdisk_read(ide_device_t* dev, size_t secno, void* dst, size_t nsecs) {
    nsecs = __MIN(nsecs, dev->size - secno);
    if (nsecs <= 0)
        return -1;

    memcpy(dst, (void*)(dev->iobase + secno * SECTOR_SIZE), nsecs * SECTOR_SIZE);  // TODOSECTOR_SIZE
    return 0;
}

static int
ramdisk_write(ide_device_t* dev, size_t secno, const void* src, size_t nsecs) {
    nsecs = __MIN(nsecs, dev->size - secno);
    if (nsecs <= 0)
        return -1;

    memcpy((void*)(dev->iobase + secno * SECTOR_SIZE), src, nsecs * SECTOR_SIZE);
}

void
ramdisk_init(uint32_t devno, ide_device_t* dev) {
    memset(dev, 0, sizeof(ide_device_t));

    byte_t* _initrd_begin;
    byte_t* _initrd_end;
    if (devno == DISK0_DEVICE_NO) {
        _initrd_begin = _binary_bin_fat32_img_start;
        _initrd_end = _binary_bin_fat32_img_end;
    } else
        panic("device not found\n");

    if (check_initrd(_initrd_begin, _initrd_end)) {
        dev->valid = 1;
        dev->sets = ~0;
        dev->size = (uint32_t)(_initrd_end - _initrd_begin) / SECTOR_SIZE;
        dev->iobase = (address_t)_initrd_begin;
        strcpy(dev->model, "KERN_INITRD");
        dev->read_secs = ramdisk_read;
        dev->write_secs = ramdisk_write;
    }
}